﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace MediaClient.Common
{
    public delegate void RealTimeWriteCompleteHandler(string discDriveName, string mediaPackName);

    public delegate void RealTimeWriteProcessHandler(string discDriveName,string mediaPackName, long completeSize);


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]

    public struct DISCTRACK_INFO
    {
        public bool bAudioTrack;
        public uint ulongStartSector;
        public uint ulongEndSector;
    };

    public enum DiscState
    { 
        LoadDiscError,      //加载光盘错误
        UnableWrite,        //光盘不可写
        LoadDiscSuccessful, //加载成功
        BurnReadyError,     //准备错误
        Burning,            //正在刻录
        BurnWriteError,     //同步刻录时错误
        BurnWriteEndError,    //正在结束刻录
        BurnSuccessful      //刻录成功
    }

    public class BurnHelper
    {

        //common version
        //[DllImport("RecLib.dll", EntryPoint="Rec_Regist")] public static extern int Rec_Regist(string code);
        [DllImport("RecLib.dll", EntryPoint = "Rec_Regist", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Rec_Regist(string code);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_SetDriver")]
        public static extern int Rec_SetDriver(string DriverName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_SetDevice")]
        public static extern int Rec_SetDevice(byte DeviceID);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetSupportedWriteModes")]
        public static extern int Rec_GetSupportedWriteModes(ref bool IsTaoSupported, ref bool IsDaoSupported, ref bool IsSaoSupported);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "Rec_GetVendorProductStrings")]
        public static extern int Rec_GetVendorProductStrings(byte[] VendorNamePtr, byte[] ProductNamePtr);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_Load")]
        public static extern int Rec_Load();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_Unload")]
        public static extern int Rec_Unload();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_EraseDisc")]
        public static extern int Rec_EraseDisc();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_IsDeviceReady")]
        public static extern int Rec_IsDeviceReady();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetDiscInfo")]
        public static extern int Rec_GetDiscInfo(ref bool IsDiscBlank, ref bool IsDiscWriteable, ref int DiscType);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetDiscInfoEx")]
        public static extern int Rec_GetDiscInfoEx(ref bool IsDiscBlank, ref bool IsDiscWriteable, ref int DiscType, ref ulong DiscRemainCapability);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetCdSpeeds")]
        public static extern int Rec_GetCdSpeeds(ref uint CurrentReadSpeed, ref uint CurrentWriteSpeed, ref uint MaximumReadSpeed, ref uint MaximumWriteSpeed);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetCdSpeedsEx")]
        public static extern int Rec_GetCdSpeedsEx(ref uint CurrentReadSpeed, ref uint CurrentWriteSpeed, ref uint MaximumReadSpeed, ref uint MaximumWriteSpeed, ref uint MinimunWriteSpeed);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetCdSpeedsEx2")]
        public static extern int Rec_GetCdSpeedsEx2(ref uint CurrentReadSpeed, ref uint CurrentWriteSpeed, ref uint MaximumReadSpeed, ref uint MaximumWriteSpeed, ref uint MinimunWriteSpeed, ref uint BestWriteSpeed);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_AddFiles")]
        public static extern int Rec_AddFiles(string SourName, string TarParentFolder, bool isMp3CD);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_AddFilesEx")]
        public static extern int Rec_AddFilesEx(string SourName, string TarParentFolder, bool isMp3CD, string TarFileName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_DeleteFiles")]
        public static extern int Rec_DeleteFiles(string TargetName, bool isFolder);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_ClearFiles")]
        public static extern int Rec_ClearFiles();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteDataCD")]
        public static extern int Rec_WriteDataCD(string VolumeName, bool IsMp3CD, bool IsTestWrite);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteDataCDEx")]
        public static extern int Rec_WriteDataCDEx(string VolumeName, bool IsMp3CD, bool IsTestWrite, bool IsMultiSession, bool IsEjectDiscAfterRecord);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteDataCDEx2")]
        public static extern int Rec_WriteDataCDEx2(string DriverName, string VolumeName, bool IsMp3CD, bool IsTestWrite, bool IsMultiSession, bool IsEjectDiscAfterRecord);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteDataCDEx2_Async")]
        public static extern int Rec_WriteDataCDEx2_Async(string DriverName, string VolumeName, bool IsMp3CD, bool IsTestWrite, bool IsMultiSession, bool IsEjectDiscAfterRecord);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteUDFDataCD")]
        public static extern int Rec_WriteUDFDataCD(string VolumeName, bool IsTestWrite);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteClose")]
        public static extern int Rec_WriteClose();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteImageToCD")]
        public static extern int Rec_WriteImageToCD(string ImageFileName, bool IsTestWrite);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteGetProgress")]
        public static extern int Rec_WriteGetProgress();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteGetProgressEx")]
        public static extern int Rec_WriteGetProgressEx(string DriverName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteGetCurrBurnFileName")]
        public static extern int Rec_WriteGetCurrBurnFileName(byte[] CurrBurnFile);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteGetCurrBurnFileNameEx")]
        public static extern int Rec_WriteGetCurrBurnFileNameEx(string DriverName, byte[] CurrBurnFile);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_StopWrite")]
        public static extern int Rec_StopWrite();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetWriteAsyncIsOverEx")]
        public static extern int Rec_GetWriteAsyncIsOverEx(string DriverName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_GetWriteAsyncErrCodeEx")]
        public static extern int Rec_GetWriteAsyncErrCodeEx(string DriverName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_VerifyDisc")]
        public static extern int Rec_VerifyDisc(string DriverName);

        //professional version
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "Rec_GetAudioFileInfo")]
        public static extern int Rec_GetAudioFileInfo(string FileName, ref uint TrackLength, ref uint SectorLength, byte[] TimeLength);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_SetImageFile")]
        public static extern int Rec_SetImageFile(string ImageFileName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteAudioCD")]
        public static extern int Rec_WriteAudioCD(bool IsTestWrite, byte[] AudioFileNames);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_SetAutoRunDisc")]
        public static extern int Rec_SetAutoRunDisc(string pAutoRunExeFileNameOfDisc, string pAutoRunIconFileNameOfDisc);

        //Advanced version
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false, EntryPoint = "Rec_GetTrackInfo")]
        public static extern int Rec_GetTrackInfo(byte DeviceId, string ImageFileName, [MarshalAs(UnmanagedType.LPArray)] ref DISCTRACK_INFO[] pDiscTrack_Info);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_SaveAudioTrack")]
        public static extern int Rec_SaveAudioTrack(byte DeviceId, int TrackIndex, string SaveFileName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_CopyDisc")]
        public static extern int Rec_CopyDisc(byte SourceDeviceId, byte TargetDeviceId, byte[] CopyTempFile);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_CopyDiscGetProgress")]
        public static extern int Rec_CopyDiscGetProgress();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_CopyStop")]
        public static extern int Rec_CopyStop();
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteVideoCD")]
        public static extern int Rec_WriteVideoCD(string VolumeName, int VCDSourceMpegFileNumber, byte[] VCDSourceMpegFileNames);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteVideoCDEx")]
        public static extern int Rec_WriteVideoCDEx(string VolumeName, bool bRecompress, int Format, int AspectRatio, int DVDSourceMpegFileNumber, byte[] DVDSourceMpegFileNames);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteSVCD")]
        public static extern int Rec_WriteSVCD(string VolumeName, bool bRecompress, int Format, int AspectRatio, int DVDSourceMpegFileNumber, byte[] DVDSourceMpegFileNames);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteDVDVideo")]
        public static extern int Rec_WriteDVDVideo(string VolumeName, int DVDSourceMpegFileNumber, byte[] DVDSourceMpegFileNames);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_WriteDVDVideoEx")]
        public static extern int Rec_WriteDVDVideoEx(string VolumeName, bool bRecompress, int Format, int AspectRatio, int DVDSourceMpegFileNumber, byte[] DVDSourceMpegFileNames);

        //Realtime version
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_SetEstimateTotalWriteSize")]
        public static extern int Rec_RealTimeWrite_SetEstimateTotalWriteSize(string DriverName, ulong size);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_Begin")]
        public static extern int Rec_RealTimeWrite_Begin(string DriverName, string VolumeName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_CreateFile")]
        public static extern int Rec_RealTimeWrite_CreateFile(string DriverName, string FilePathName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_WriteFile")]
        public static extern int Rec_RealTimeWrite_WriteFile(string DriverName, byte[] pBuf, int BufSize);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_CloseFile")]
        public static extern int Rec_RealTimeWrite_CloseFile(string DriverName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_End")]
        public static extern int Rec_RealTimeWrite_End(string DriverName);
        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_GetDiscRemainCapacity")]
        public static extern int Rec_RealTimeWrite_GetDiscRemainCapacity(string DriverName, ref ulong DiscRemainCapability);

        [DllImport("RecLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Rec_RealTimeWrite_WriteFileEx")]
        public static extern int Rec_RealTimeWrite_WriteFileEx(string DriverName, byte[] pBuf, int BufSize);

        [DllImport("kernel32", EntryPoint = "GetDriveType")]
        public static extern uint GetDriverType(string name);
        [DllImport("shell32.dll")]
        public static extern int ShellExecute(IntPtr hwnd, string lpszOp, string lpszFile, string lpszParams, string lpszDir, int FsShowCmd);


        public static event RealTimeWriteCompleteHandler RealTimeWriteComplete;

        public static event RealTimeWriteProcessHandler RealTimeWriteProcess;

        public BurnHelper()
        {
            //
        }


        //judge current disc can be recorded
        public static bool JudgeDisc()
        {
            //Judge whether the recorder is ready
            if (Rec_IsDeviceReady() != 1)
            {
                MessageBox.Show("Recorder is not ready, please retry!", "Info");
                return false;
            }

            bool IsDiscBlank = false;
            bool IsDiscWriteable = false;
            int DiscType = 0;
            ulong DiscRemainCapability = 0;
            if (Rec_GetDiscInfoEx(ref IsDiscBlank, ref IsDiscWriteable, ref DiscType, ref DiscRemainCapability) != 1)
            {
                MessageBox.Show("Get disc information failed, please retry!", "Info");
                return false;
            }

            //Only follow two conditions all compatible, the disc can be to record
            if ((IsDiscWriteable) && (DiscRemainCapability > 0))
            { }
            else
            {
                MessageBox.Show("The disc can't be to record, please retry!", "Info");
                return false;
            }
            return true;
        }

        private static string GetResultInfo(int ret)
        {
            string ss;
            switch (ret)
            {

                case 1: ss = "调用成功"; break;
                case 0: ss = "调用失败"; break;
                case -5: ss = "发送操作命令失败"; break;
                case -6: ss = "发送刻录命令失败"; break;
                case -7: ss = "错误的命令请求"; break;
                case -8: ss = "错误的驱动器号"; break;
                case -10: ss = "错误的操作命令"; break;
                case -15: ss = "设备没有准备好或者设备忙"; break;
                case -44: ss = "空白盘片检查错误"; break;
                case -50: ss = "该盘片是空白盘片"; break;
                case -100: ss = "用户终止了刻录操作"; break;
                case -109: ss = "文件创建失败"; break;
                case -113: ss = "写盘片错误"; break;
                case -124: ss = "刻录的数据量超过了盘片容量"; break;
                case -144: ss = "错误的轨道类型"; break;
                case -156: ss = "不能识别的镜像文件"; break;
                case -157: ss = "不能刻录到DVD盘片"; break;
                case -158: ss = "在目标盘上没有足够的空间"; break;
                case -159: ss = "在硬盘上没有足够的空间保存临时文件"; break;
                case -160: ss = "复制盘片时临时文件创建错误"; break;
                case -161: ss = "复制盘片时找不到临时文件"; break;
                case -162: ss = "复制盘片时使用的文件格式不正确"; break;
                case -301: ss = "不是可写盘片"; break;
                case -304: ss = "读盘片错误"; break;
                case -305: ss = "读取轨道信息错误"; break;
                case -510: ss = "解码音乐文件错误"; break;
                case -511: ss = "准备刻录时盘片错误"; break;
                case -512: ss = "文件容量太大"; break;
                case -601: ss = "转换文件初始化错误"; break;
                case -602: ss = "转换文件错误"; break;
                case -603: ss = "转换文件开始错误"; break;
                default: ss = "其它错误: 错误码= " + ret.ToString(); break;
            }

            return ss;
        }

        /// <summary>
        /// 返回所有光驱信息
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string,DiscState> InitAndGetDriversName()
        {
            Dictionary<string, DiscState> dicDiscDrive = new Dictionary<string, DiscState>();
            Rec_Regist("408258204166");
            String[] drives = Environment.GetLogicalDrives();
            for (int i = 0; i < drives.Length; i++)
            {
                if (BurnHelper.GetDriverType(drives[i]) != 5)  //DRIVE_CDROM
                    continue;
                if (Rec_SetDriver(drives[i]) != 1)
                    continue;
                //Judge is recordable device
                bool IsTaoSupported = false;
                bool IsDaoSupported = false;
                bool IsSaoSupported = false;
                if (Rec_GetSupportedWriteModes(ref IsTaoSupported, ref IsDaoSupported, ref IsSaoSupported) != 1)
                    continue;
                if (!IsTaoSupported || !IsDaoSupported || !IsSaoSupported)
                    continue;

                string sVendorName = "";
                string sProductName = "";
                GetVendorString(ref sVendorName, ref sProductName);
                string sDriverName = drives[i].Substring(0, 2) + sVendorName + sProductName;
                dicDiscDrive.Add(sDriverName, SetDriver(sDriverName));
                
            }
            return dicDiscDrive;
        }

        public static int JudgeDisc(Dictionary<string, ulong> discDrive)
        {
            int flag = 0;
            if (JudgeDisc() == true)
            {
                bool IsDiscBlank = false;
                bool IsDiscWriteable = false;
                int DiscType = 0;
                ulong discReminCapacity = 0;
                flag = Rec_GetDiscInfoEx(ref IsDiscBlank, ref IsDiscWriteable, ref DiscType, ref discReminCapacity);
                if (flag != 1)
                {
                    MessageBox.Show(GetResultInfo(flag));
                    flag = 2;
                }
                else if (IsDiscWriteable == false)
                    MessageBox.Show("磁盘不可写。");
                else
                {
                    foreach (var key in discDrive.Keys)
                    {
                        flag = 0;
                        if (discReminCapacity < discDrive[key])
                        {
                            MessageBox.Show(" 磁盘容量不符合所选择的磁盘类型。", BaseForm.MessageBoxCaption);
                            flag = 2;
                            break;
                        }
                    }
                }
            }
            return flag;
        }

        static private void GetVendorString(ref string sVendorName, ref string sProductName)
        {
            byte[] bVendorName = new byte[32];
            byte[] bProductName = new byte[32];

            Rec_GetVendorProductStrings(bVendorName, bProductName);

            sVendorName = System.Text.Encoding.Default.GetString(bVendorName);
            sVendorName = sVendorName.Substring(0, sVendorName.IndexOf("\0"));
            sProductName = System.Text.Encoding.Default.GetString(bProductName);
            sProductName = sProductName.Substring(0, sProductName.IndexOf("\0"));

        }

        public static DiscState SetDriver(string driverName)
        {
            DiscState state;

            if (Rec_SetDriver(driverName) != 1)
            {
                state = DiscState.LoadDiscError;
            }
            else
            {
                state = DiscState.LoadDiscSuccessful;
            }
            return state;
        }

        /// <summary>
        /// 开始同步刻录
        /// </summary>
        /// <param name="discVolumName">光盘卷标</param>
        /// <param name="buffeSize">每次写入到光盘的文件大小</param>
        /// <param name="discFilePath">文件保存在光盘的位置</param>
        /// <param name="m_sDriver">刻录这个文件的光驱名称</param>
        /// <param name="captureFileFullPath">需要刻录的源文件路径</param>
        /// <param name="writeFileLength">返回当前刻录的大小</param>
        /// <param name="state">返回当前刻录状态</param>
        static public void SynchronizationBurnData(string discVolumName, int writeSizeOneTimeMB, string discDriveName,Dictionary<string,string> burnFiles, ref DiscState state, ref ulong discReminCapacity,bool endBurn,string mediaPackName)
        {
            int ret = 1;
            
            if ( ret != 1)
            {
                MessageBox.Show(GetResultInfo(ret));
                return;
            };
            if (JudgeDisc() == false)
                return;
            bool IsDiscBlank = false;
            bool IsDiscWriteable = false;
            int DiscType = 0;
            Rec_GetDiscInfoEx(ref IsDiscBlank, ref IsDiscWriteable, ref DiscType, ref discReminCapacity);

            int buffeSize = 1024 * 1024 * writeSizeOneTimeMB;
            byte[] byData = new byte[ buffeSize];
            ret = Rec_RealTimeWrite_Begin(discDriveName, discVolumName);
            if (ret != 1)
            {
                MessageBox.Show(GetResultInfo(ret));
                state = DiscState.BurnReadyError;
                return;
            }
            long process = 0;
            int readCount = 0;
            foreach (var sourcFile in burnFiles.Keys)
            {
                long position = 0;
                ret = Rec_RealTimeWrite_CreateFile(discDriveName, burnFiles[sourcFile]);
                if (ret != 1)
                {
                    MessageBox.Show(GetResultInfo(ret));
                    state = DiscState.BurnReadyError;
                    return;
                }
                FileStream sFile = null;
                try
                {
                    sFile = new FileStream(sourcFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    while (position < sFile.Length)
                    {
                        sFile.Seek(position, SeekOrigin.Begin); //position
                        readCount = sFile.Read(byData, 0, buffeSize);
                        position += readCount;
                        //position = sFile.Position;
                        if (readCount > 0)
                        {
                            ret = Rec_RealTimeWrite_WriteFileEx(discDriveName, byData, readCount);
                            while (ret == -131)
                            {
                                Thread.Sleep(6000);
                                ret = Rec_RealTimeWrite_WriteFileEx(discDriveName, byData, readCount);
                            }

                            //ret = Rec_RealTimeWrite_WriteFile(discDriveName, byData, readCount);
                            if (ret != 1)
                            {
                                MessageBox.Show(GetResultInfo(ret));
                                state = DiscState.BurnWriteError;
                                return;
                            }
                            else
                            {
                                process += readCount;
                                if (RealTimeWriteProcess != null)
                                    RealTimeWriteProcess(discDriveName, mediaPackName, process);
                                state = DiscState.Burning;
                                //Rec_RealTimeWrite_GetDiscRemainCapacity(discDriveName, ref discReminCapacity);
                                //bool IsDiscBlank = false;
                                //bool IsDiscWriteable = false;
                                //int DiscType = 0;
                                //Rec_GetDiscInfoEx(ref IsDiscBlank, ref IsDiscWriteable, ref DiscType, ref discReminCapacity);
                            }
                        }
                        Thread.Sleep(330);
                    }
                }
                finally
                {
                    ret = Rec_RealTimeWrite_CloseFile(discDriveName);
                    if (ret != 1)
                        MessageBox.Show(GetResultInfo(ret));
                    sFile.Dispose();
                    sFile.Close();
                }
            }

            ret = Rec_RealTimeWrite_End(discDriveName);
            
            if (ret != 1)
            {
                if (ret != 1)
                    MessageBox.Show(GetResultInfo(ret));
                state = DiscState.BurnWriteEndError;
                return;
            }
            else
            {
                state = DiscState.BurnSuccessful;

                //Rec_RealTimeWrite_GetDiscRemainCapacity(discDriveName, ref discReminCapacity);
                
                if (RealTimeWriteComplete != null)
                    RealTimeWriteComplete(discDriveName, mediaPackName);
            }
            if (endBurn)
                Rec_Unload();
        }

        public static ulong GetReminCapacity(string m_sDriver)
        {
            ulong reminCapacity = 0;
            Rec_RealTimeWrite_GetDiscRemainCapacity(m_sDriver, ref reminCapacity);
            return reminCapacity;
        }

        public static string GetVolumeName(string driverName)
        {
            string name = "";
            DriveInfo[] driverInfo = DriveInfo.GetDrives();
            foreach (var driver in driverInfo)
            {
                if (driver.Name.ToLower() == driverName.ToLower())
                {
                    name = driver.VolumeLabel;
                    break;
                }
            }
            return name;
        }

    }
}
